<!DOCTYPE html>
<html>
  <head>
    <title>Donut Chart</title>
    <script type="text/javascript" src="../../d3.js"></script>
    <script type="text/javascript" src="../../d3.layout.js"></script>
    <style type="text/css">

body {
  font: 10px sans-serif;
}

    </style>
  </head>
  <body>
    <script type="text/javascript">

var w = 400,
    h = 400,
    r1 = Math.min(w, h) / 2,
    r0 = r1 * .6,
    n = 10,
    q = 0,
    data0 = d3.range(n).map(Math.random),
    data1 = d3.range(n).map(Math.random),
    data,
    color = d3.scale.category20(),
    arc = d3.svg.arc(),
    donut = d3.layout.pie();

var vis = d3.select("body")
  .append("svg:svg")
    .attr("width", w)
    .attr("height", h);

vis.selectAll("g.arc")
    .data(arcs(data0, data1))
  .enter().append("svg:g")
    .attr("class", "arc")
    .attr("transform", "translate(" + r1 + "," + r1 + ")")
  .append("svg:path")
    .attr("fill", function(d, i) { return color(i); })
    .attr("d", arc);

window.addEventListener("keypress", swap, false);

function arcs(data0, data1) {
  var arcs0 = donut(data0),
      arcs1 = donut(data1),
      i = -1,
      arc;
  while (++i < n) {
    arc = arcs0[i];
    arc.innerRadius = r0;
    arc.outerRadius = r1;
    arc.next = arcs1[i];
  }
  return arcs0;
}

function swap() {
  d3.selectAll("g.arc > path")
      .data(++q & 1 ? arcs(data0, data1) : arcs(data1, data0))
      .each(transitionSplit);
}

// 1. Wedges split into two rings.
function transitionSplit(d, i) {
  d3.select(this)
    .transition().duration(1000)
      .attrTween("d", tweenArc({
        innerRadius: i & 1 ? r0 : (r0 + r1) / 2,
        outerRadius: i & 1 ? (r0 + r1) / 2 : r1
      }))
      .each("end", transitionRotate);
}

// 2. Wedges translate to be centered on their final position.
function transitionRotate(d, i) {
  var a0 = d.next.startAngle + d.next.endAngle,
      a1 = d.startAngle - d.endAngle;
  d3.select(this)
    .transition().duration(1000)
      .attrTween("d", tweenArc({
        startAngle: (a0 + a1) / 2,
        endAngle: (a0 - a1) / 2
      }))
      .each("end", transitionResize);
}

// 3. Wedges then update their values, changing size.
function transitionResize(d, i) {
  d3.select(this)
    .transition().duration(1000)
      .attrTween("d", tweenArc({
        startAngle: d.next.startAngle,
        endAngle: d.next.endAngle
      }))
      .each("end", transitionUnite);
}

// 4. Wedges reunite into a single ring.
function transitionUnite(d, i) {
  d3.select(this)
    .transition().duration(1000)
      .attrTween("d", tweenArc({
        innerRadius: r0,
        outerRadius: r1
      }));
}

function tweenArc(b) {
  return function(a) {
    var i = d3.interpolate(a, b);
    for (var key in b) a[key] = b[key]; // update data
    return function(t) {
      return arc(i(t));
    };
  };
}

    </script>
  </body>
</html>
